package mypazar.jenamodel;

import java.util.List;
import java.util.Random;
import java.util.Vector;

import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;

public class InitialPazarBeliefBase {

	private static final int MAX_PRICE = 8;

	/**
	 * Max quantity of a person can buy any product.
	 */
	private static final int MAX_QUANTITY = 10;

	private List<String> products;

	/**
	 * Creates belief base in RDF model type.
	 * 
	 * @param agentName
	 *            the name of the agent
	 * @return created belief base.
	 */
	public Model createRDFModel(String agentName) {
		Model beliefBase = ModelFactory.createDefaultModel();

		if (agentName.startsWith(PazarVocabulary.SALESMAN_NAME_PREFIX)) {
			createSalesmanBeliefBase(beliefBase, agentName);

		} else if (agentName.startsWith(PazarVocabulary.PERSON_NAME_PREFIX)) {
			createPersonBeliefBase(beliefBase, agentName);
		}

		return beliefBase;
	}

	/**
	 * Creates the product list to sell.
	 * 
	 * @return created product list.
	 */
	public List<String> getProducts() {
		if (products == null) {
			products = new Vector<String>();
			products.add("apple");
			products.add("orange");
			products.add("banana");
		}
		return products;
	}

	/**
	 * Creates product resource to buy
	 * 
	 * @param beliefBase
	 *            belief base of the person.
	 * @param productName
	 *            product name of the created product.
	 * @return created product individual.
	 */
	private Resource createProductToBuy(Model beliefBase, String productName) {
		// Creates product individual...
		Resource productNode = beliefBase.createResource(
				PazarVocabulary.PRODUCT_NAME_URI,
				PazarRDFS.PERSON_PRODUCT_CLASS);

		// Set name of the product...
		productNode.addProperty(
				beliefBase.getProperty(PazarVocabulary.PRODUCT_NAME_URI),
				productName, XSDDatatype.XSDstring);
		// Generate and set quantity to buy of the product...
		productNode.addProperty(
				beliefBase.getProperty(PazarVocabulary.QUANTITY_URI),
				Integer.toString(newQuantityToBuy()), XSDDatatype.XSDint);
		return productNode;
	}

	/**
	 * Creates person agent's resource.
	 * 
	 * @param model
	 * @param personURI
	 * @param personName
	 * @return
	 */
	private Resource createPerson(Model model, String personURI,
			String personName) {
		return model.createResource(personURI, PazarRDFS.PERSON_CLASS)
				.addProperty(model.getProperty(PazarVocabulary.PERSON_AD_URI),
						personName, XSDDatatype.XSDstring);
	}

	/**
	 * Creates person agent's belief base.
	 * 
	 * @param beliefBase
	 * @param agentName
	 */
	private void createPersonBeliefBase(Model beliefBase, String agentName) {
		Resource productNode = createProductToBuy(beliefBase, getProducts()
				.get(findProductId(agentName)));

		// Positions (x, y)
		Resource positionNode = beliefBase
				.createResource(PazarVocabulary.PERSON_POSITION_URI,
						PazarRDFS.POSITION_CLASS)
				.addProperty(beliefBase.getProperty(PazarVocabulary.POS_X_URI),
						"0", XSDDatatype.XSDinteger)
				.addProperty(beliefBase.getProperty(PazarVocabulary.POS_Y_URI),
						"0", XSDDatatype.XSDinteger);

		// Person resources
		Resource personNode = createPerson(beliefBase,
				PazarVocabulary.NS_URI + agentName, agentName).addProperty(
				beliefBase.getProperty(PazarVocabulary.POSITION_URI),
				positionNode).addProperty(
				beliefBase.getProperty(PazarVocabulary.PRODUCT_URI),
				productNode);

		@SuppressWarnings("unused")
		Resource pazarNode = beliefBase
				.createResource(PazarVocabulary.NS_URI + "pazar",
						PazarRDFS.PAZAR_CLASS)
				.addProperty(
						beliefBase
								.getProperty(PazarVocabulary.PERSON_URI_PREFIX),
						personNode);
	}

	/**
	 * Creates salesman agent's individual.
	 * 
	 * @param model
	 * @param salesmanURI
	 * @param salesmanName
	 * @return
	 */
	private Resource createSalesman(Model model, String salesmanURI,
			String salesmanName) {
		return model.createResource(salesmanURI, PazarRDFS.SALESMAN_CLASS)
				.addProperty(
						model.getProperty(PazarVocabulary.SALESMAN_AD_URI),
						salesmanName, XSDDatatype.XSDstring);
	}

	/**
	 * Creates salesman agent's belief base
	 * 
	 * @param beliefBase
	 * @param agentName
	 */
	private void createSalesmanBeliefBase(Model beliefBase, String agentName) {
		Resource productNode = createProductToSell(beliefBase, getProducts()
				.get(findProductId(agentName)));

		// Positions (x, y)
		Resource positionNode = beliefBase
				.createResource(PazarVocabulary.SALESMAN_POSITION_URI,
						PazarRDFS.POSITION_CLASS)
				.addProperty(beliefBase.getProperty(PazarVocabulary.POS_X_URI),
						"0", XSDDatatype.XSDinteger)
				.addProperty(beliefBase.getProperty(PazarVocabulary.POS_Y_URI),
						"0", XSDDatatype.XSDinteger);

		// Salesman resource
		Resource salesmanNode = createSalesman(beliefBase,
				PazarVocabulary.NS_URI + agentName, agentName).addProperty(
				beliefBase.getProperty(PazarVocabulary.POSITION_URI),
				positionNode).addProperty(
				beliefBase.getProperty(PazarVocabulary.PRODUCT_URI),
				productNode);

		@SuppressWarnings("unused")
		Resource pazarNode = beliefBase
				.createResource(PazarVocabulary.NS_URI + "pazar",
						PazarRDFS.PAZAR_CLASS)
				.addProperty(
						beliefBase
								.getProperty(PazarVocabulary.PERSON_URI_PREFIX),
						salesmanNode);
	}

	/**
	 * Creates product resource using given product name.
	 * 
	 * @param beliefBase
	 *            belief base of the salesman.
	 * @param productName
	 *            product name of selling product.
	 * @return created product resource.
	 */
	private Resource createProductToSell(Model beliefBase, String productName) {
		// create product individual...
		Resource productNode = beliefBase.createResource(
				PazarVocabulary.PRODUCT_NAME_URI,
				PazarRDFS.SALESMAN_PRODUCT_CLASS);
		// set name of the product...
		productNode.addProperty(
				beliefBase.getProperty(PazarVocabulary.PRODUCT_NAME_URI),
				productName, XSDDatatype.XSDstring);
		// generate and set quantity of the product...
		productNode.addProperty(
				beliefBase.getProperty(PazarVocabulary.QUANTITY_URI),
				Integer.toString(newQuantityToSell()), XSDDatatype.XSDint);
		// generate and set price of the product...
		productNode.addProperty(
				beliefBase.getProperty(PazarVocabulary.PRICE_URI),
				Integer.toString(newPrice()), XSDDatatype.XSDint);

		return productNode;
	}

	/**
	 * Specifies the index of the product in the {@link #products} according to
	 * the given agent name. It uses agent number to specify the product number.
	 * 
	 * 
	 * @param agentName
	 *            name of the agent to determine its product to sell or buy.
	 * @return index of the product in the {@link #products} list.
	 */
	private int findProductId(String agentName) {
		return Integer.parseInt(agentName.substring(agentName.length() - 1))
				% getProducts().size();
	}

	/**
	 * Generates a new random integer to set new price value
	 * 
	 * @return
	 */
	private int newPrice() {
		return new Random(System.currentTimeMillis()).nextInt(MAX_PRICE) + 1;
	}

	/**
	 * Generates a random integer to set buying product's quantity.
	 * 
	 * @return
	 */
	private int newQuantityToBuy() {
		return new Random(System.currentTimeMillis()).nextInt(MAX_QUANTITY) + 1;
	}

	/**
	 * Generates a random integer to set selling product's quantity.
	 * 
	 * @return
	 */
	private int newQuantityToSell() {
		return new Random(System.currentTimeMillis()).nextInt(MAX_QUANTITY + 5) + 11;
	}
}
